package naga.x.net.proxy;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.core.session.IoSession;

import naga.x.game.time.TimeUpdater;
import naga.x.net.Packet;
import naga.x.net.PacketHandler;
import naga.x.net.SessionObserver;
import naga.x.net.impl.ClientSession;
import naga.x.net.impl.pomelo.PomeloEncoder;
import naga.x.net.impl.pomelo.PomeloPacket;
import naga.x.util.SessionUtils;

/**
 * 代理连接
 * @author yang.li
 *
 */
public class ProxyClientSession extends ClientSession {

	protected long id; // proxySessionId << 32 | clientSessionId
	protected int clientSessionId; // 客户端与代理服连接的session id,由代理服分配
	protected Map<Object, Object> attrs;
//	protected long lastReceivedPacketTimestamp;
	
	public ProxyClientSession(IoSession session, PacketHandler handler, int clientSessionId, SessionObserver observer) {
		super(session, handler, observer);
		this.clientSessionId = clientSessionId;
		int proxySessionId = (int) session.getAttribute(ProxyClientSessionService.SESSION_ID);
		this.id = ((long) proxySessionId << 32) | clientSessionId;
		this.attrs = new ConcurrentHashMap<Object, Object>();
//		this.lastReceivedPacketTimestamp = TimeUpdater.getInstance().now();
	}
	
	@Override
	public long getId() {
		return id;
	}

//	@Override
//	public SocketAddress getRemoteAddress() {
//		return session.getRemoteAddress();
//	}
	
	@Override
	public <T> T getAttribute(Object key) {
		return (T) attrs.get(key);
	}
	
	public <T> T getAttribute(Object key, T defaultVal) {
		return (T) attrs.getOrDefault(key, defaultVal);
	}

	@Override
	public <T> T setAttribute(Object key, T value) {
		return (T) attrs.put(key, value);
	}

	@Override
	public <T> T removeAttribute(Object key) {
		return (T) attrs.remove(key);
	}
	
//	@Override
//	public boolean isConnected() {
//		return state == State.CONNECTED && session.isConnected();
//	}
//
//	@Override
//	public boolean isClosing() {
//		return state == State.CLOSING || session.isClosing();
//	}
	
	@Override
	public void close(boolean immediately) {
		if (isConnected()) {
			ProxyPacket p = new ProxyPacket(ProxyOpCode.SESSION_CLOSE, null, clientSessionId, -1, (byte) 0);
			send(p);
			state = State.CLOSING;
		}
	}
	
	@Override
	public void received(Packet packet) {
		super.received(packet);
//		lastReceivedPacketTimestamp = TimeUpdater.getInstance().now();
		setAttribute(SessionUtils.LAST_HEARTBEAT_TIME, TimeUpdater.getInstance().now());
	}

	@Override
	public void send(Packet packet) {
		if (isConnected()) {
			if (packet instanceof PomeloPacket) {
				PomeloPacket pomelo = (PomeloPacket) packet;
				ProxyPacket proxy = new ProxyPacket(pomelo.getOpCode(), 128, clientSessionId, pomelo.getSerial(), pomelo.getPackageType());
				proxy.put(PomeloEncoder.encode(pomelo));
				proxy.getData().flip();
				packet = proxy;
			}
			session.write(packet);
		}
	}

	@Override
	public void dispose() {
		packets.clear();
		attrs.clear();
	}

//	@Override
//	public boolean update() {
//		if (isClosing()) {
//			state = State.CLOSED;
//			observer.fireSessionClosed(this);
//			dispose();
//			return false;
//		}
//		if (!isConnected()) {
//			return true;
//		}
//		if (HEARTBEAT_TIMEOUT > 0) {
//			if (TimeUpdater.getInstance().now() - lastReceivedPacketTimestamp >= HEARTBEAT_TIMEOUT) {
//				close(false);
//				return true;
//			}
//		}
//		if (packets.isEmpty()) {
//			return true;
//		}
//		Packet packet;
//		while ((packet = packets.poll()) != null) {
//			handler.handle(this, packet);
//		}
//		return true;
//	}
	
	
	
}
